﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using Crm.Plugins.DuplicateChecker.Domain;
using Microsoft.Crm.Sdk;

namespace Crm.Plugins.DuplicateChecker.Data{
    /// <summary>
    /// Retrieves configuration information from the <c>CrmService</c>/>.
    /// </summary>
    public class CrmConfigurationRepository : CrmRepository{
        private readonly string _schemaPrefix;

        /// <summary>
        /// Initializes a new instance of the <see cref="CrmConfigurationRepository"/> class.
        /// </summary>
        /// <param name="crmService">An instance of <c>CrmService</c>.</param>
        /// <param name="schemaPrefix">The schema prefix used for custom entities in CRM.</param>
        public CrmConfigurationRepository(ICrmService crmService, string schemaPrefix) : base(crmService){
            _schemaPrefix = schemaPrefix;
        }

        /// <summary>
        /// Gets the configuration information from the <c>CrmService</c> for the entity to check for duplicates.
        /// </summary>
        /// <param name="entityName">Name of the entity to check for duplicates.</param>
        /// <returns></returns>
        public CrmConfiguration Get(string entityName){
            if (String.IsNullOrEmpty(entityName)){
                throw new InvalidOperationException("EntityName cannot be null or empty.");
            }
            string fetchXmlResponse = executeFetch(entityName);
            IEnumerable<string> keyAttributeNames = parseResponse(fetchXmlResponse);
            if (keyAttributeNames.Count() != 1){
                throw new InvalidOperationException(String.Format("Configuration information was not found for Entity[{0}].", entityName));
            }
            return new CrmConfiguration{EntityName = entityName, KeyAttribute = keyAttributeNames.First()};
        }

        private string executeFetch(string entityName){
            string fetchXml =
                string.Format(
                    "<fetch><entity name='{0}duplicatechecker'><attribute name='{0}keyattribute' /><filter><condition attribute='{0}entityname' operator='eq' value='{1}' /></filter></entity></fetch>",
                    _schemaPrefix, entityName);

            return _crmService.Fetch(fetchXml);
        }

        private IEnumerable<string> parseResponse(string fetchXmlResponse){
            XDocument xdocument = XDocument.Parse(fetchXmlResponse);
            return from item in xdocument.Descendants(_schemaPrefix + "keyattribute") select item.Value;
        }
    }
}